<template>
	<el-select ref='select' v-model="val" :filterable="filterable" :remote="true" :placeholder="placeholder"
		:value-key="valueKey" :loading="loading" :clearable="showClose" no-match-text="暂无数据" :multiple="multiple"
		:popper-append-to-body="popperAppendToBody" v-bind="$attrs" @hook:mounted="visileChange"
		@visible-change="visileChange" @blur.native.capture="onblur" @click.native="click"
		@keyup.enter.native="keyupEnter" @clear="clearThis" @change="change">
		<!--v-on="$listeners"-->
		<!-- @focus="focus" -->
		<!-- :remote-method="remoteMethod" 这个方法,IOS端输入有BUG -->
		<el-option v-for="(o,i) in optionList" :key="o[valueKey]" :label="o[valueLabel]" :value="o[valueKey]">
			<slot :row="o" :$index="i"></slot>
		</el-option>
	</el-select>
</template>
<script>
	import common from "/src/common/common.js";

	export default {
		name: "remoteselect",
		props: {
			url: String, //加载数据地址
			valueKey: {
				//选项显示属性
				type: String,
				default: "Value"
			},
			valueLabel: {
				type: String,
				default: "Label"
			},
			//Key的类型
			valueType: {
				type: String,
				default: "String"
			},
			ajaxDataResult: { //数据所在属性,空则取data
				type: String,
				default: "Result"
			},

			timeout: {
				type: Number,
				default: 800
			},
			options: { //初始化数据集合
				type: Array,
				default () {
					return [];
				}
			},
			popperAppendToBody: {
				type: Boolean,
				default: true
			},
			placeholder: {
				type: String,
				//default: "请选择"
			},
			getMethod: { //获取数据Method,默认为post
				type: String,
				default: "post"
			},
			//默认属性
			filterable: { //是否可以搜索
				type: Boolean,
				default: true
			},
			multiple: { //是否可以多选
				type: Boolean,
				default: false
			},
			clearable: { //是否显示清空按钮
				type: Boolean,
				default: true
			},
			queryKey: {
				type: Number | String,
				default: "Value__Label"
			},
			//搜索所用key值
			queryParameters: {
				type: Object,
				default () {
					return {};
				}
			},
			//搜索附带数据
			value: {
				type: Number | String | Object,
				default: null
			}, //当前值
		},
		watch: {
			value(n, old) {
				if (n == old) return;
				//console.log("watch_value", n, old);
				if (this.optionList != null && this.optionList.length == 0) {
					this.remoteMethod(n, true, true);
					return;
				}
				//多个的不请求
				if (this.multiple == false) {
					//单个的,值里面没有,才去请求
					var has = false;
					for (var i = 0; i < this.optionList.length; i++) {
						var item = this.optionList[i];
						if (item == null) continue;
						if ((item[this.valueKey] == null && n == null) || (item[this.valueKey] != null && n != null &&
								item[this.valueKey].toString() == n.toString())) {
							has = true;
							break;
						}
					}
					if (has == false) {
						this.remoteMethod(n, true, true);
					}
				}
				if (n == null) return;
				this.initShowLabel();
			},
			options(n, old) {
				if ((n == null && old == null) || (JSON.stringify(n) == JSON.stringify(old))) return;
				//console.log("watch_options", n, old);
				this.init();
			},
			url(n, old) {
				if (n == old) return;
				//console.log("watch_url", n, old);
				if (n != old) {
					this.remoteMethod(null, true, true);
				}
			},
			queryParameters(n, old) {
				if ((n == null && old == null) || (JSON.stringify(n) == JSON.stringify(old))) return;
				//console.log("watch_queryParameters", n, old, n == old);
				this.remoteMethod(null, true, true);
			}
		},
		computed: {
			val: {
				get() {
					var r = this.getValueFormat();
					//console.log("computed__val", r);
					return r;
				},
				set(n, old) {
					//赋值
					//console.log("computed.val.set", n, this.value);
					if (!!n && this.multiple && typeof(n) == "string") {
						var arr = n.split(',');
						if (arr[0] == null || arr[0] == "") arr = [];
						this.selectChange(arr);
					} else {
						this.selectChange(n);
					}
				}
			},
			oldQueryLabel() {
				if (this.oldQueryObj == null) return null;
				let r = this.oldQueryObj[this.valueLabel];
				if (r != null) r = r.toString();
				return r;
			},
			oldQueryValueKey() {
				if (this.oldQueryObj == null) return null;
				let r = this.oldQueryObj[this.valueKey];
				if (r != null) r = r.toString();
				return r;
			}
		},

		data() {
			return {
				optionList: [], //ajax结果
				loading: false,
				queryValue: null,
				oldQueryObj: null,
				settimeout: null,
				firstSearch: true, //第一次,已nameKey的data传递查询
				showClose: false
			};
		},

		mounted() {
			//console.log("mounted", this.$refs.select);
		},

		created() {
			//this.key = 'remoteselect' + Math.random();
			//console.log("created", this.url, this.value, this._uid, this.key);
			window.remoteselect = this;
			this.init();
			this.firstSearch = false;
		},

		methods: {
			init() {
				//有值的情况,才去设置一个已查询过数据了的
				var val = this.getValueFormat();
				if (((!!val && (typeof(this.value) == "string" || typeof(this.value) == "number")) ||
						((!!val && this.multiple && val.length > 0))) &&
					this.optionList.length == 0) {
					var ops = this.options;
					if (ops != null && ops.length > 0) {
						this.optionList = ops;
						this.val = this.value;
					} else {
						if (this.multiple && val.length > 0) {
							this.remoteMethod(val, true, true);
						} else {
							this.remoteMethod(val, true, true);
						}
					}
				}
				//解决IOS输入了不去请求的情况
				this.$nextTick(() => {
					this.$nextTick(() => {
						this.bindRemote();
					})
				});
			},
			initShowLabel() {
				//控件不重置,重置值,再赋值,第二次会出现BUG,不显示标签
				this.$nextTick(() => {
					setTimeout(() => {
						if (this.multiple) return;
						var $select = this.$refs.select;
						var label = $select.selectedLabel;
						//console.log("label", label, $select.selectedLabel);
						if (!label) {
							//console.log("$select.selected.currentLabel", $select.selected.currentLabel);
							if (!!$select.selected && !!$select.selected.currentLabel) {
								label = $select.selected.currentLabel;
								//console.log("label set", label);
								$select.selectedLabel = label;
							}
						}
					}, 100);
				});
			},
			getValueFormat() {
				if (this.value == null) return null;
				if (this.value instanceof Array && !this.multiple) {
					if (this.valueType == "String") {
						return this.value[0] == null ? null : this.value[0].toString();
					}
					return this.value[0];
				}
				if (this.multiple && typeof(this.value) == "string") {
					var arr = [];
					var tempArr = this.value.split(',');
					for (var i = 0; i < tempArr.length; i++) {
						var item = tempArr[i];
						if (item == null || item == "") continue;
						if (this.valueType == "String") {
							arr.push(item.toString());
						} else {
							arr.push(item);
						}
					}
					return arr;
				}
				if (this.valueType == "String") {
					if (this.multiple && this.value instanceof Array) {
						for (var i = 0; i < this.value.length; i++) {
							this.value[i] = this.value[i].toString();
						}
						return this.value;
					}
					if (this.value instanceof Array) {
						return this.value;
					}
					return this.value.toString();
				}
				return this.value;
			},
			eventListener(e) {
				//console.log("eventListener", e.target.value);
				this.remoteMethod(e.target.value);
			},
			bindRemote() { //必须this.$nextTick 解决IOS下remote-method输入第一个字没反应的BUG
				const innerElInput = this.$refs.select; //.$refs.reference;
				var inputs = innerElInput.$el.getElementsByTagName('input');
				//console.log("bindRemote", innerElInput, inputs, inputs.length);
				//获取input元素
				const input = inputs[0];
				//主动触发远程搜索方法
				input.removeEventListener('input', this.eventListener);
				input.addEventListener('input', this.eventListener);
			},
			dealOptionvalueType(list) {
				if (list == null || list.length == 0) return [];
				var isString = this.valueType == "String";
				for (var i = 0; i < list.length; i++) {
					var item = list[i];
					var val = item[this.valueKey];
					if (val == null) continue;
					if (isString == false) {
						item[this.valueKey] = Number(val);
					} else {
						item[this.valueKey] = val.toString();
					}
				}
				return list;
			},
			keyupEnter() {
				if (this.queryValue) {
					//this.selectChange(this.queryValue);
					this.$refs.select.handleClose();
				}
			},
			focusClickCommon() { //选中的选项,要出现在下拉里面
				//console.log("focusClickCommon");
				if (this.optionList.length > 0) {
					if (this.oldQueryObj != null && this.multiple == false) { //多个的,不加
						let has = common.tool.arrContains(this.optionList, this.oldQueryObj, this.valueKey);
						if (has == false) {
							this.optionList.push(this.oldQueryObj);
						}
					}
					return;
				}
				this.remoteMethod(null, true, true);
			},
			focus(a) {
				this.$emit("focus", a);
				this.focusClickCommon();
			},
			click(a) {
				this.$emit("click", a);
				this.focusClickCommon();
			},
			visileChange(e) { //hook:mounted visible-change调用
				if (e && this.clearable) { // 打开下拉框 显示可清空按钮,解决要点击两次的BUG
					this.showClose = true;
				}
				//解决不弹出输入框的BUG
				this.$nextTick(() => {
					if (!e) {
						const {
							select
						} = this.$refs;
						const input = select.$el.querySelector('.el-input__inner');
						input.removeAttribute('readonly');
					}
				});
			},
			onblur() { //失去焦点 不会自动隐藏输入框的BUG
				setTimeout(() => {
					if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { //判断iPhone|iPad|iPod|iOS
						this.$refs.select.blur();
					}
					this.showClose = false
					var scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0;
					window.scrollTo(0, Math.max(scrollHeight - 1, 0));
				}, 100);
			},
			clearThis($event) {
				//console.log("clearThis");
				this.selectChange(null);
				if (this.optionList.length < 5) {
					this.remoteMethod(null, true, true);
				}
				this.$emit("clear", $event);
			},
			change(n) {
				//console.log("change", n);
				this.$nextTick(() => {
					var selected = this.getSelected();
					this.$emit("change", n, selected);

					this.$emit("selectchange", selected);
				});
			},
			selectChange(n) {
				if (n instanceof Array && !this.multiple) {
					n = n[0];
				}
				var option;
				for (var i = 0; i < this.optionList.length; i++) {
					if (this.optionList[i][this.valueKey] == n) {
						option = this.optionList[i];
						this.oldQueryObj = option;
						break;
					}
				}
				this.$emit("input", n);
				//console.log("selectChange", option, n);
				if (option == null) return;
				//会自行触发一次change事件的,不需要调用this.$emit,因为加了绑定事件v-on="$listeners"到最底层去,所以会自行触发
				//this.$emit("change", option || n);
			},
			getSelected() {
				var r = [];
				var isArray = this.value instanceof Array;
				if (this.value == null) return null;
				if (isArray && this.value.length == 0) return [];
				for (var i = 0; i < this.optionList.length; i++) {
					var item = this.optionList[i];
					if (isArray) {
						for (var j = 0; j < this.value.length; j++) {
							var v = this.value[j];
							if (item[this.valueKey].toString() == v.toString()) {
								r.push(item);
								break;
							}
						}
					} else {
						if (item[this.valueKey].toString() == this.value.toString()) {
							r.push(item);
							break;
						}
					}
				}
				if (isArray) {
					return r;
				}

				if (r.length > 0) return r[0];
				return null;
			},
			setOptions(list) {
				this.optionList = list;
			},
			getQueryKey() { //多个的时候,要带上主键查询条件
				if (this.queryKey == null || this.queryKey == "") {
					return this.valueKey;
				}
				if (this.multiple) {
					if (this.queryKey.indexOf(this.valueKey) == -1) {
						var r = this.queryKey + "__" + this.valueKey;
						return r;
					}
					return this.queryKey;
				}
				return this.queryKey;
			},
			remoteMethod(query, notimeout, nocache) {
				if (query == null || query == undefined) query = "";
				//console.log("remoteMethod", query, this.firstSearch, notimeout, nocache, this.oldQueryLabel, this.oldQueryValueKey, this.queryParameters);
				this.queryValue = query;
				if (!this.url) return;
				var data = {
					index: 1,
					size: 20
				};
				try {
					data = Object.assign(data, this.queryParameters);
				} catch (e) {}
				if (this.settimeout != null) {
					clearTimeout(this.settimeout);
					this.settimeout = null;
				}
				let timeout = !!notimeout ? 0 : this.timeout; //没有延时

				var queryKey = this.getQueryKey();
				//console.log("queryKey", queryKey);
				data[queryKey] = query || "";
				// if (this.firstSearch) {
				//     if (query == this.value) {
				//         data[queryKey] = undefined;
				//         delete data[queryKey];
				//     }
				//     data[this.valueKey] = this.value;
				// }
				this.settimeout = setTimeout(() => {
					if (nocache != true && (query == this.oldQueryLabel || query == this.oldQueryValueKey)) {
						return;
					}
					// console.log("data", data);
					// return;
					var postData = common.tool.toKeyValue(data);
					common.tool.post(this.url, postData).then((res) => {
						var resultList = [];
						if (!!this.ajaxDataResult) {
							resultList = res[this.ajaxDataResult];
						} else {
							resultList = res.Result;
						}
						if (resultList == null || resultList.length == 0) {
							this.optionList = [];
							return;
						}
						resultList = this.dealOptionvalueType(resultList);
						//2秒内阻止重复请求 id值变成text的情况
						this.setOldQueryObj(query, resultList);
						if (!this.queryValue && this.multiple == false) {
							// this.$nextTick(() => {
							// 	try {
							// 		this.$refs.select.selectedLabel = '';
							// 	} catch (e) {}
							// });
						}
						this.optionList = [];
						//console.log("resultList", resultList);
						this.optionList = resultList;
						this.initShowLabel2();
					});
				}, timeout);
			},
			initShowLabel2() {
				//console.log("initShowLabel2", this.optionList);
				this.$nextTick(() => {
					if (this.multiple) {
						return;
					}
					var selectObj = this.getSelected();
					if (selectObj != null) {
						var showLabel = selectObj[this.valueLabel];
						if (this.$refs.select == null) {
							//console.log("this.$refs.select");
							return;
						}
						//console.log(this.$refs.select.selectedLabel, this.$refs.select.selected)
						if (this.$refs.select.selectedLabel != showLabel) {
							this.$refs.select.selectedLabel = showLabel;
							try {
								this.$refs.select.selected.currentLabel = showLabel;
							} catch (e) {}
						}
					}
				});
				//this.$refs.select.$forceUpdate();
			},
			setOldQueryObj(query, resultList) {
				try {
					if (query == null) {
						this.oldQueryObj = null;
						return;
					}
					var key = query;
					for (var i = 0; i < resultList.length; i++) {
						var item = resultList[i];
						var temp = item[this.valueKey];
						if (temp != null && temp.toString() == key.toString()) {
							this.oldQueryObj = item;
							return;
						}
					}
					this.oldQueryObj = null;
				} catch (e) {}
			}
		}
	}
</script>
